<script lang="ts">
import { defineComponent, onUnmounted, ref } from 'vue'
import useDialogStore from '@/stores/modules/dialog'
import { MessageType, SendStatus } from '@/stores/modules/dialog'
import type { DialogItem } from '@/stores/modules/dialog'

const dialogStore = useDialogStore()

export default defineComponent({
  name: 'RecorderButton',
  emits: ['recording-complete'],
  setup(_props, { emit }) {
    const isRecording = ref(false)
    const audioUrl = ref<string | null>(null)
    const recordingTime = ref(0)

    let mediaRecorder: MediaRecorder | null = null
    let audioChunks: BlobPart[] = []
    let startTime = 0
    let timerInterval: NodeJS.Timeout | null = null

    const updateRecordingTime = () => {
      recordingTime.value = (Date.now() - startTime) / 1000
    }

    const startRecording = async () => {
      try {
        // 重置之前的录音
        audioChunks = []
        audioUrl.value = null
        recordingTime.value = 0

        // 请求麦克风权限
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true })

        // 创建MediaRecorder实例
        mediaRecorder = new MediaRecorder(stream)

        // 收集音频数据
        mediaRecorder.ondataavailable = (event) => {
          audioChunks.push(event.data)
        }

        // 录音结束时的处理
        mediaRecorder.onstop = () => {
          const audioBlob = new Blob(audioChunks, { type: 'audio/wav' })
          audioUrl.value = URL.createObjectURL(audioBlob)

          // 向父组件发送录音完成事件
          // eslint-disable-next-line vue/custom-event-name-casing
          emit('recording-complete', {
            blob: audioBlob,
            url: audioUrl.value,
            duration: recordingTime.value,
          })

          // 停止所有音轨
          stream.getTracks().forEach(track => track.stop())
        }

        // 开始录音
        mediaRecorder.start()
        isRecording.value = true
        startTime = Date.now()

        // 启动计时器
        timerInterval = setInterval(updateRecordingTime, 100)
      } catch (error) {
        console.error('录音失败:', error)
        // eslint-disable-next-line no-alert
        alert('无法访问麦克风，请确保已授予麦克风权限。')
      }
    }

    const stopRecording = () => {
      if (mediaRecorder && isRecording.value) {
        mediaRecorder.stop()
        isRecording.value = false
        console.log('录音结束', timerInterval)
        // 清除计时器
        if (timerInterval !== null) {
          clearInterval(timerInterval)
          timerInterval = null
        }
      }
    }

    function send() {
      // showToast(`已发送${recordingTime.value.toFixed(0)}秒语音`)
      if (audioUrl.value) {
        const msg: DialogItem = dialogStore.addMsg({ type: MessageType.AUDIO, content: audioUrl.value, duration: recordingTime.value })
        setTimeout(() => {
          // msg.status = SendStatus.SUCCESS
          dialogStore.setStatus(msg.recordId, SendStatus.SUCCESS)
        }, 2000);
        // URL.revokeObjectURL(audioUrl.value)
        audioUrl.value = null
        recordingTime.value = 0
      }
    }

    // 组件卸载时清理资源
    onUnmounted(() => {
      if (timerInterval !== null) {
        clearInterval(timerInterval)
      }
      if (audioUrl.value) {
        URL.revokeObjectURL(audioUrl.value)
      }
    })

    return {
      isRecording,
      audioUrl,
      recordingTime,
      startRecording,
      stopRecording,
      send,
    }
  },
})
</script>

<template>
  <div class="recorder-container overflow-visible">
    <div v-if="recordingTime > 0 && !audioUrl" class="recording-info">
      录音时长: {{ recordingTime.toFixed(0) }}秒
    </div>
    <div v-else-if="audioUrl" class="audio-preview">
      <audio :src="audioUrl" controls />
    </div>
    <van-button v-if="audioUrl" class="w-full" type="primary" @click="send()">
      发送
    </van-button>
    <van-button :class="{ recording: isRecording }" class="recorder-button w-full" @mousedown="startRecording"
      @mouseleave="stopRecording" @mouseup="stopRecording" @touchstart.prevent="startRecording"
      @touchend.prevent="stopRecording">
      <span v-if="!isRecording">{{ audioUrl ? '重新录制' : '按住录音' }}</span>
      <span v-else>松开结束</span>
    </van-button>
  </div>
</template>

<style scoped>
.recorder-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}

.recorder-button:hover {
  background-color: #45a049;
}

.recorder-button.recording {
  background-color: #f44336;
  transform: scale(1.1);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(244, 67, 54, 0.7);
  }

  70% {
    box-shadow: 0 0 0 15px rgba(244, 67, 54, 0);
  }

  100% {
    box-shadow: 0 0 0 0 rgba(244, 67, 54, 0);
  }
}

.audio-preview {
  audio {
    position: absolute;
    left: 50%;
    top: 30px;
    transform: translate(-50%, -50%);
    height: 40px;
  }

  height: 40px;
  width: 100%;
}

.recording-info {
  line-height: 40px;
  font-size: 1rem;
  color: #333;
}
</style>
